
#include <QtGui>
#include <QtOpenGL>

#include <math.h>

#include "glwidget.h"
#include <fstream>
#include <iostream>

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>


//! [0]
GLWidget::GLWidget(QWidget *parent)
    : QGLWidget(parent)
{
    object = 0;
    xRot = 0;
    yRot = 0;
    zRot = 0;
	
	bkgColor = QColor::fromRgb(50, 50, 50);
	objColor = QColor::fromRgb(100, 100, 200);

	cam_x = 0;
	cam_y = 0;
	cam_z = 5;
	cam_look_x = 0;
	cam_look_y = 0;
	cam_look_z = 0;
	cam_up_x = 0;
	cam_up_y = 1;
	cam_up_z = 0;

	trans_inc = 0.6;

	trans_x = 0;
	trans_y = 0;
	trans_z = 0;
}
//! [0]

//! [1]
GLWidget::~GLWidget()
{
    makeCurrent();
    glDeleteLists(object, 1);
}
//! [1]

//! [2]
QSize GLWidget::minimumSizeHint() const
{
    return QSize(50, 50);
}
//! [2]

//! [3]
QSize GLWidget::sizeHint() const
//! [3] //! [4]
{
    return QSize(400, 400);
}
//! [4]

//! [5]
void GLWidget::setXRotation(int angle)
{
    normalizeAngle(&angle);
    if (angle != xRot) {
        xRot = angle;
        emit xRotationChanged(angle);
        updateGL();
    }
}
//! [5]

void GLWidget::setYRotation(int angle)
{
    normalizeAngle(&angle);
    if (angle != yRot) {
        yRot = angle;
        emit yRotationChanged(angle);
        updateGL();
    }
}

void GLWidget::setZRotation(int angle)
{
    normalizeAngle(&angle);
    if (angle != zRot) {
        zRot = angle;
        emit zRotationChanged(angle);
        updateGL();
    }
}

//! [6]
void GLWidget::initializeGL()
{
    qglClearColor(bkgColor.dark());
    object = makeObject();
    glShadeModel(GL_FLAT);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
}
//! [6]

//! [7]
void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    
	glTranslated(trans_x, trans_y, trans_z);

    glRotated(xRot / 16.0, 1.0, 0.0, 0.0);
    glRotated(yRot / 16.0, 0.0, 1.0, 0.0);
    glRotated(zRot / 16.0, 0.0, 0.0, 1.0);
    glCallList(object);
}
//! [7]

//! [8]
void GLWidget::resizeGL(int width, int height)
{
	glViewport(0, 0, width, height);
	

	glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

	gluPerspective(30, (double)width/height, 0.1, 200);
	gluLookAt(cam_x, cam_y, cam_z, cam_look_x, cam_look_y, cam_look_z, cam_up_x, cam_up_y, cam_up_z);
	

    glMatrixMode(GL_MODELVIEW);
	
}
//! [8]

//! [9]
void GLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
}
//! [9]

//! [10]
void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - lastPos.x();
    int dy = event->y() - lastPos.y();

    if (event->buttons() & Qt::LeftButton) {
        setXRotation(xRot + 8 * dy);
        setYRotation(yRot + 8 * dx);
    } else if (event->buttons() & Qt::RightButton) {
        setXRotation(xRot + 8 * dy);
        setZRotation(zRot + 8 * dx);
    }
    lastPos = event->pos();
}
//! [10]

GLuint GLWidget::makeObject()
{
    GLuint list = glGenLists(1);
    glNewList(list, GL_COMPILE);

	qglColor(objColor.light());

	std::vector<double> pt;


	BOOST_FOREACH( pt, m_points ) {
		qglColor(QColor::fromRgb(200, 200, pt[3]*255));

		glPushMatrix();
		glTranslated(pt[0], pt[1], pt[2]);
		GLUquadric* obj = gluNewQuadric();
		gluSphere(obj, 0.01, 16, 16);
		glPopMatrix();
	}


    glEndList();
    return list;
}

void GLWidget::normalizeAngle(int *angle)
{
    while (*angle < 0)
        *angle += 360 * 16;
    while (*angle > 360 * 16)
        *angle -= 360 * 16;
}


void GLWidget::zoomIn() {
	trans_z += trans_inc;
	
	updateGL();
}

void GLWidget::zoomOut() {
	trans_z -= trans_inc;

	updateGL();
}

void GLWidget::updateObject() {
	object = makeObject();
}